#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

public static class BaiduFolderContextTranslate
{
    // ===== 右键菜单 =====
    [MenuItem("Assets/翻译文件夹内子文件", true)]
    private static bool ValidateRun()
    {
        return GetSelectedFolders().Count > 0;
    }

    [MenuItem("Assets/翻译文件夹内子文件")]
    private static void Run()
    {
        var folders = GetSelectedFolders();
        var settings = FindOrCreateSettings();
        if (settings == null)
        {
            EditorUtility.DisplayDialog("缺少设置",
                "没有找到 BaiduTranslateSettings。\n\n请在 Project 中创建：Right Click → Create → Tools → Baidu Translate Settings，填入 appId 和 secretKey。", "好的");
            return;
        }
        if (string.IsNullOrEmpty(settings.appId) || string.IsNullOrEmpty(settings.secretKey))
        {
            Selection.activeObject = settings;
            EditorUtility.DisplayDialog("请完善配置", "AppId 或 SecretKey 为空，请在 Inspector 中填写。", "去填写");
            return;
        }

        _ = TranslateAndRenameAsync(folders, settings);
    }

    // 可选：仅预览（Dry Run）
    [MenuItem("Assets/预览翻译（Dry Run）", true)]
    private static bool ValidatePreview() => ValidateRun();

    [MenuItem("Assets/预览翻译（Dry Run）")]
    private static void Preview()
    {
        var folders = GetSelectedFolders();
        var settings = FindOrCreateSettings();
        if (settings == null)
        {
            EditorUtility.DisplayDialog("缺少设置",
                "没有找到 BaiduTranslateSettings。\n\n请在 Project 中创建：Right Click → Create → Tools → Baidu Translate Settings。", "好的");
            return;
        }
        _ = TranslateAndRenameAsync(folders, settings, dryRun:true);
    }

    // ===== 主逻辑 =====
    private static async Task TranslateAndRenameAsync(List<string> folderPaths, BaiduTranslateSettings s, bool dryRun = false)
    {
        int renamed = 0, skipped = 0, errors = 0;
        var sb = new StringBuilder();
        try
        {
            var allItems = new List<(string path, bool isDir)>();

            foreach (var f in folderPaths)
            {
                if (s.includeSubfolders)
                {
                    if (s.processFolders)
                    {
                        // 文件夹重命名：先子级再父级（深度优先，避免父目录先改导致路径失效）
                        var dirs = Directory.GetDirectories(f, "*", SearchOption.AllDirectories)
                            .OrderByDescending(d => d.Count(c => c == Path.DirectorySeparatorChar));
                        allItems.AddRange(dirs.Select(d => (d, true)));
                    }
                    // 文件
                    var files = Directory.GetFiles(f, "*", SearchOption.AllDirectories)
                        .Where(p => !p.EndsWith(".meta", StringComparison.OrdinalIgnoreCase));
                    allItems.AddRange(files.Select(p => (p, false)));
                }
                else
                {
                    if (s.processFolders)
                    {
                        // 顶层子文件夹
                        var dirs = Directory.GetDirectories(f, "*", SearchOption.TopDirectoryOnly)
                            .OrderByDescending(d => d.Count(c => c == Path.DirectorySeparatorChar));
                        allItems.AddRange(dirs.Select(d => (d, true)));
                    }
                    // 顶层文件
                    var files = Directory.GetFiles(f, "*", SearchOption.TopDirectoryOnly)
                        .Where(p => !p.EndsWith(".meta", StringComparison.OrdinalIgnoreCase));
                    allItems.AddRange(files.Select(p => (p, false)));
                }
            }

            if (!s.processFolders)
            {
                // 默认只处理文件
                allItems = allItems.Where(t => !t.isDir).ToList();
            }

            // 按总数显示进度
            int total = allItems.Count;
            int index = 0;

            var slugger = new Slugger(s);

            foreach (var (path, isDir) in allItems)
            {
                index++;
                string displayName = isDir ? new DirectoryInfo(path).Name : Path.GetFileName(path);
                EditorUtility.DisplayProgressBar("翻译并重命名", $"{index}/{total}  {displayName}", (float)index / total);

                try
                {
                    if (!PassExtFilter(path, s))
                    {
                        skipped++;
                        if (s.verboseLog) sb.AppendLine($"[Skip] 扩展名过滤：{displayName}");
                        continue;
                    }

                    string stem = isDir ? displayName : Path.GetFileNameWithoutExtension(displayName);
                    string ext  = isDir ? "" : Path.GetExtension(displayName);

                    if (s.onlyWhenContainsChinese && !RegexChinese.IsMatch(stem))
                    {
                        skipped++;
                        if (s.verboseLog) sb.AppendLine($"[Skip] 无中文：{displayName}");
                        continue;
                    }

                    // 发送翻译
                    string translated = await BaiduTranslateAsync(stem, s);
                    await Task.Delay(Mathf.Max(0, s.throttleMs)); // 节流

                    // 根据命名风格生成目标名
                    string targetStem = slugger.BuildName(translated, stem);
                    if (string.IsNullOrEmpty(targetStem))
                    {
                        skipped++;
                        sb.AppendLine($"[Skip] 翻译为空：{displayName}");
                        continue;
                    }

                    // 长度限制
                    if (targetStem.Length > s.maxNameLength)
                        targetStem = targetStem.Substring(0, s.maxNameLength);

                    string dir = isDir ? Directory.GetParent(path).FullName : Path.GetDirectoryName(path);
                    string targetPath = Path.Combine(dir, targetStem + ext);
                    targetPath = EnsureUnique(targetPath, s.separator);

                    if (targetPath == path)
                    {
                        skipped++;
                        continue;
                    }

                    if (dryRun)
                    {
                        renamed++;
                        sb.AppendLine($"[预览] {(isDir ? "文件夹" : "文件")}: {displayName}  ->  {Path.GetFileName(targetPath)}");
                    }
                    else
                    {
                        if (isDir) Directory.Move(path, targetPath);
                        else File.Move(path, targetPath);
                        renamed++;
                        if (s.verboseLog) sb.AppendLine($"[OK] {(isDir ? "文件夹" : "文件")}: {displayName} -> {Path.GetFileName(targetPath)}");
                    }
                }
                catch (Exception ex)
                {
                    errors++;
                    sb.AppendLine($"[Error] {displayName}\n{ex}");
                }
            }
        }
        finally
        {
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            string title = dryRun ? "预览完成" : "处理完成";
            var msg = $"{title}\n重命名：{renamed}\n跳过：{skipped}\n错误：{errors}";
            Debug.Log($"[BaiduRename]\n{msg}\n—— 详细日志 ——\n{sb}");
            EditorUtility.DisplayDialog("翻译并重命名", msg, "好的");
        }
    }

    // ===== 翻译请求（百度通用翻译 API）=====
    private static async Task<string> BaiduTranslateAsync(string text, BaiduTranslateSettings s)
    {
        const string url = "https://api.fanyi.baidu.com/api/trans/vip/translate";
        string salt = UnityEngine.Random.Range(100000, 999999).ToString();
        string signRaw = s.appId + text + salt + s.secretKey;
        string sign = MD5Hex(signRaw);

        var form = new List<IMultipartFormSection>
        {
            new MultipartFormDataSection("q", text),
            new MultipartFormDataSection("from", s.fromLang),
            new MultipartFormDataSection("to", s.toLang),
            new MultipartFormDataSection("appid", s.appId),
            new MultipartFormDataSection("salt", salt),
            new MultipartFormDataSection("sign", sign),
        };

        using (var www = UnityWebRequest.Post(url, form))
        {
            www.timeout = 15;
            await SendAsync(www);

#if UNITY_2020_2_OR_NEWER
            bool ok = www.result == UnityWebRequest.Result.Success;
#else
            bool ok = !www.isHttpError && !www.isNetworkError;
#endif
            if (!ok)
            {
                Debug.LogError($"[BaiduRename] 翻译请求失败：{text} | {www.error}");
                return string.Empty;
            }

            var json = www.downloadHandler.text;
            // 用 JsonUtility 解析
            var resp = JsonUtility.FromJson<BaiduResp>(json);
            if (resp != null && resp.trans_result != null && resp.trans_result.Length > 0)
            {
                // 多段结果拼接
                var dst = string.Join(" ", resp.trans_result.Select(r => r.dst));
                return dst;
            }
            // 尝试错误结构
            var err = JsonUtility.FromJson<BaiduError>(json);
            if (err != null && !string.IsNullOrEmpty(err.error_code))
            {
                Debug.LogError($"[BaiduRename] API 错误 {err.error_code}: {err.error_msg} | 原文：{text}");
            }
            else
            {
                Debug.LogError($"[BaiduRename] 无法解析响应：{json}");
            }
            return string.Empty;
        }
    }

    private static Task SendAsync(UnityWebRequest req)
    {
        var tcs = new TaskCompletionSource<bool>();
        var op = req.SendWebRequest();
        op.completed += _ => tcs.TrySetResult(true);
        return tcs.Task;
    }

    // ===== 小工具 =====
    private static List<string> GetSelectedFolders()
    {
        var list = new List<string>();
        foreach (var obj in Selection.objects)
        {
            string rel = AssetDatabase.GetAssetPath(obj);
            if (AssetDatabase.IsValidFolder(rel))
            {
                string abs = Path.GetFullPath(rel);
                list.Add(abs);
            }
        }
        return list;
    }

    private static BaiduTranslateSettings FindOrCreateSettings()
    {
        var guids = AssetDatabase.FindAssets("t:BaiduTranslateSettings");
        if (guids != null && guids.Length > 0)
        {
            string path = AssetDatabase.GUIDToAssetPath(guids[0]);
            return AssetDatabase.LoadAssetAtPath<BaiduTranslateSettings>(path);
        }
        // 自动创建一个默认设置，方便用户填写
        var inst = ScriptableObject.CreateInstance<BaiduTranslateSettings>();
        string savePath = "Assets/Editor/BaiduTranslateSettings.asset";
        Directory.CreateDirectory("Assets/Editor");
        AssetDatabase.CreateAsset(inst, savePath);
        AssetDatabase.SaveAssets();
        Debug.LogWarning($"已创建默认设置：{savePath}，请在 Inspector 填好 appId/secretKey。");
        Selection.activeObject = inst;
        return inst;
    }

    private static bool PassExtFilter(string path, BaiduTranslateSettings s)
    {
        if (s.onlyExtensions == null || s.onlyExtensions.Length == 0) return true;
        string ext = Path.GetExtension(path).TrimStart('.').ToLowerInvariant();
        return s.onlyExtensions.Any(e => string.Equals(e.Trim('.').ToLowerInvariant(), ext));
    }

    private static string EnsureUnique(string targetPath, string sep)
    {
        string dir = Path.GetDirectoryName(targetPath);
        string name = Path.GetFileNameWithoutExtension(targetPath);
        string ext = Path.GetExtension(targetPath);

        string candidate = targetPath;
        int i = 1;
        while (File.Exists(candidate) || Directory.Exists(candidate))
        {
            candidate = Path.Combine(dir, $"{name}{(string.IsNullOrEmpty(sep) ? "-" : sep)}{i}{ext}");
            i++;
        }
        return candidate;
    }

    private static string MD5Hex(string s)
    {
        using (var md5 = MD5.Create())
        {
            var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(s));
            var sb = new StringBuilder();
            foreach (var b in bytes) sb.Append(b.ToString("x2"));
            return sb.ToString();
        }
    }

    // ===== 名称清洗 / 中文检测 =====
    private static readonly Regex RegexChinese = new Regex(@"[\u3400-\u9FFF]", RegexOptions.Compiled);

    private class Slugger
    {
        private readonly Regex allowedChars;
        private readonly BaiduTranslateSettings s;

        public Slugger(BaiduTranslateSettings settings)
        {
            s = settings;
            string safe = "a-zA-Z";
            if (s.keepNumbers) safe += "0-9";
            if (s.keepUnderscore) safe += "_";
            if (s.keepDash) safe += "\\-";
            // 允许的字符以外 -> 用空格替换，便于后续切词
            allowedChars = new Regex($"[^ {safe} ]+", RegexOptions.Compiled);
        }

        /// <summary>
        /// 根据命名风格构建文件名（不含扩展名）
        /// </summary>
        public string BuildName(string translated, string fallbackFrom)
        {
            // 1) 清洗
            string src = !string.IsNullOrWhiteSpace(translated) ? translated : fallbackFrom;
            src = src.Trim();

            // 把不允许的字符替换为空格
            string cleaned = allowedChars.Replace(src, " ");

            // 统一把下划线/短横线也当成分隔符 -> 空格（先切词，后面再按风格重组）
            cleaned = cleaned.Replace('_', ' ').Replace('-', ' ');

            // 切词
            var parts = cleaned
                .Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                .ToList();

            if (parts.Count == 0) return string.Empty;

            // 2) 按命名风格重组
            switch (s.namingStyle)
            {
                case NamingStyle.PascalCase:
                    return string.Concat(parts.Select(Capitalize));

                case NamingStyle.CamelCase:
                {
                    var first = parts[0].ToLowerInvariant();
                    var rest  = string.Concat(parts.Skip(1).Select(Capitalize));
                    return first + rest;
                }

                case NamingStyle.SnakeLower:
                    return string.Join("_", parts.Select(p => p.ToLowerInvariant()));

                case NamingStyle.SnakeUpper:
                    return string.Join("_", parts.Select(p => p.ToUpperInvariant()));

                case NamingStyle.KebabLower:
                    return string.Join("-", parts.Select(p => p.ToLowerInvariant()));

                case NamingStyle.TrainCase:
                    return string.Join("-", parts.Select(Capitalize));

                case NamingStyle.CustomSeparator:
                default:
                    return BuildWithCustomSeparator(parts);
            }
        }

        private string BuildWithCustomSeparator(List<string> parts)
        {
            // 用用户的 separator 重新拼接
            string sep = s.separator ?? "";
            IEnumerable<string> seq = parts;

            if (s.lowerCase) seq = seq.Select(p => p.ToLowerInvariant());
            // 如果选择了“空格转横杠”且分隔符不是"-"，则先把空格换成横杠再按分隔符连接
            string joined = string.Join(string.IsNullOrEmpty(sep) ? " " : sep, seq);

            if (s.replaceSpaceWithDash && sep != "-")
                joined = joined.Replace(" ", "-");

            if (s.collapseRepeatSeparators && !string.IsNullOrEmpty(sep))
            {
                string pattern = Regex.Escape(sep) + "{2,}";
                joined = Regex.Replace(joined, pattern, sep);
            }

            // 修剪首尾分隔符
            if (!string.IsNullOrEmpty(sep))
            {
                string edge = $"^{Regex.Escape(sep)}+|{Regex.Escape(sep)}+$";
                joined = Regex.Replace(joined, edge, "");
            }
            return joined;
        }

        private static string Capitalize(string word)
        {
            if (string.IsNullOrEmpty(word)) return word;
            var lower = word.ToLowerInvariant();
            if (lower.Length == 1) return lower.ToUpperInvariant();
            return char.ToUpperInvariant(lower[0]) + lower.Substring(1);
        }
    }

    // ===== API 响应结构 =====
    [Serializable] private class BaiduResp { public string from; public string to; public TransItem[] trans_result; }
    [Serializable] private class TransItem { public string src; public string dst; }
    [Serializable] private class BaiduError { public string error_code; public string error_msg; }
}
#endif